home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
awe2-0_1.lha
/
awe2-0.1
/
Src
/
RCS
/
HardwareContext-mips.cc,v
< prev
next >
Wrap
Text File
|
1989-10-24
|
7KB
|
248 lines
head 1.1;
branch ;
access ;
symbols ;
locks grunwald:1.1; strict;
comment @@;
1.1
date 89.10.24.13.08.34; author grunwald; state Exp;
branches ;
next ;
desc
@@
1.1
log
@Initial revision
@
text
@// This may look like C code, but it is really -*- C++ -*-
//
// Copyright (C) 1988 University of Illinois, Urbana, Illinois
//
// written by Dirk Grunwald (grunwald@@cs.uiuc.edu)
//
#include "HardwareContext.h"
#include "HardwareContextP.h"
#include "CpuMultiplexor.h"
#include "Thread.h"
#include "assert.h"
#include <stream.h>
//
// Many machines have the same (or very similar) stack format.
// The 68K & 32K are examples of such machines.
//
// The const *registers* defines the number of additional longwords
// needed on the stack past the last frame pointer. This value needs
// to jibe with the one in HardwareContext-<arch>.s.
//
const long MagicStackMarker = 0x464f4f20; // this says 'FOO '
#define ALL_REGISTERS \
asm (" " : : :\
"$0", "at", "v0", "v1",\
"a0", "a1", "a2", "a3", \
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",\
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",\
"t8", "t9",\
"k0", "k1", "gp", "sp", "fp", "ra",\
"$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",\
"$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",\
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",\
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31" );\
static int expectedBytesSavedInContext = 112;
static int numberOfBytesSavedInContext = 0;
static int numberOfQuadsSavedInContext = 0;
HardwareContext::HardwareContext (int check, unsigned size)
{
checkStackLimits = check;
stackBase = 0;
stackEnd = 0;
stackMax = 0;
stackSize = 0;
stackCheck = 0;
stackMallocAt = 0;
if (size > 0) {
stackSize = size;
stackMallocAt = new void *[ stackSize ];
//
// stackBase should point to the first writeable cell of the
// new stack.
//
stackEnd = stackMallocAt;
stackBase = &stackMallocAt[stackSize-1];
}
else {
//
// Have the main process figure out how many registers
// (actually, Quads) are pushed when we save an entire context.
// Do this by calling magicSwitchTo with itself. This has
// the side-effect of storing fp & sp in the context.
//
magicSwitchTo(this);
numberOfBytesSavedInContext = (long) fp - (long) sp;
if ( numberOfBytesSavedInContext != expectedBytesSavedInContext ){
cerr << "error: " << __FILE__ << ", line " << int(__LINE__) << "\n";
cerr << "numberOfBytesSavedInContext = " << int(numberOfBytesSavedInContext) << "\n";
cerr << "expectedBytesSavedInContext = " << int(expectedBytesSavedInContext) << "\n";
exit(1);
}
numberOfQuadsSavedInContext = numberOfBytesSavedInContext / 4;
}
}
#ifdef UNDEF
void
HardwareContext::magicSwitchTo(HardwareContext *to)
{
register long theSp asm("sp");
register long theFp asm("fp");
ALL_REGISTERS;
sp = theSp;
fp = theFp;
theSp = to -> sp;
theFp = to -> fp;
}
#else
void
HardwareContext::magicSwitchTo(HardwareContext *to)
{
ALL_REGISTERS;
asm(" sw $29,%0" : : "m" (sp));
asm(" sw $30,%0" : : "m" (fp));
asm(" lw $29,%0" : "=g" (to -> sp));
asm(" lw $30,%0" : "=g" (to -> fp));
}
#endif
void
HardwareContext::stackOverflow()
{
register unsigned depth = stackBase - getSp();
if (stackMax < depth) {
stackMax = depth;
}
if ( stackMax >= stackSize ) {
cerr << "\nStack overflow\n";
cerr << " getSp() = " << hex(long(getSp()));
cerr << " and stackBase = " << hex(long(stackBase)) << "\n";
cerr << *this << "\n";
cerr << "Current task is \n";
cerr << *(CurrentThread());
cerr << "\n";
cerr.flush();
}
assert( stackMax < stackSize );
assert( *stackCheck == MagicStackMarker );
}
//
// Unlike other architectures, the MIPS processor passes arguments
// in registers. Thus, startOff will assume that *this* is stored
// in $a0 -- this may not be true, because we're not causing a0,etc
// to be saved & restored. In general, compilers may save/restore
// the argument registers in other registers. Hence, this hack.
//
// We have the new thread return to __magicReturnFunction with four
// arguments explicitly stored in the stack. We load the first of these
// two arguments, which is the value of *this* to be passed to the
// function addressed in the second argument. Clear?
//
extern "C" {
void __magicReturnFunction();
};
asm(" .ent __magicReturnFunction");
asm(" .globl __magicReturnFunction");
asm("__magicReturnFunction:");
asm(" lw $4,0($30)");
asm(" lw $31,4($30)");
asm(" j $31");
asm(" .end __magicReturnFunction");
void
HardwareContext::buildReturnFrame(void *returnThis, voidFuncP returnAddress)
{
//
// To build a thread, we return to the first address of startOff,
// which will use the current FP & SP to build a local context,
// and then call the user main.
//
// startOff needs to have a valid frame. The return address for this
// frame is NULL, since we never exit procedure startOff.
//
stackCheck = (long *) stackBase;
register HardwareContextQuad **stack;
stack = (HardwareContextQuad **) stackBase;
HardwareContextQuad **FP[4];
HardwareContextQuad **SP[4];
/////////////// FIRST FRAME
// space for four args
FP[0] = stack;
stack -= 2;
stackCheck = (long *) stack;
*(stack--) = (HardwareContextQuad *) MagicStackMarker;
SP[0] = stack;
*(stack--) = 0; // return address
// provide space for four args a0..a4 and put
// return address in space for a1, and this for that fcn
// in a0. __magicReturnFunction will read these from the stack
// and jump to the return address with *this* set properly.
stack -= 2;
*(stack--) = (HardwareContextQuad *) returnAddress;
*(stack) = (HardwareContextQuad *) returnThis;
/////////////// SECOND FRAME
FP[1] = stack;
stack -= (numberOfQuadsSavedInContext-1); // leave space for ....
*(stack--) = (HardwareContextQuad *) FP[1];
*(stack) = (HardwareContextQuad *) __magicReturnFunction;
SP[1] = stack;
fp = (HardwareContextQuad) FP[1];
sp = (HardwareContextQuad) SP[1];
#ifdef DEBUG
cerr << "[HardwareContext-mips] Build stack for " << hex(long(this)) << "\n";
cerr << "[HardwareContext-mips] FP[0] = " << hex(long(FP[0])) << "\n";
cerr << "[HardwareContext-mips] SP[0] = " << hex(long(SP[0])) << "\n";
cerr << "[HardwareContext-mips] FP[1] = " << hex(long(FP[1])) << "\n";
cerr << "[HardwareContext-mips] SP[1] = " << hex(long(SP[1])) << "\n";
#endif
}
void
HardwareContext::classPrintOn(ostream& s)
{
s << "[HardwareContext] Stack spans " << hex(long(stackEnd));
s << " to " << hex(long(stackBase));
s << " used is " << (stackMax) << " of " << stackSize << "\n";
s << "[HardwareContext] fp = " << hex(long(fp));
s << " sp = " << hex(long(sp));
long p = *( (long *) fp );
s << " @@fp = " << hex(p) << "\n";
}
static
void PrintSingleStackFrame()
{
}
@